package org.aplikator.server.descriptor;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.aplikator.client.descriptor.EntityDTO;
import org.aplikator.client.descriptor.FormDTO;
import org.aplikator.client.descriptor.ViewDTO;
import org.aplikator.server.Context;
import org.aplikator.server.persistence.PersisterTriggers;

import com.google.common.base.Preconditions;

public class View extends ServerDescriptorBase {

    private QueryGenerator queryGenerator;

    public PersisterTriggers trigger;

    private Entity entity;

    private List<Property<? extends Serializable>> properties = new ArrayList<Property<? extends Serializable>>();

    private Property<? extends Serializable> sortProperty;

    private Form form;

    private int pageSize = DEFAULT_PAGE_SIZE;

    private static final int DEFAULT_PAGE_SIZE = 15;

    public View(Entity entity) {
        super(entity.getId().substring(entity.getId().indexOf(TYPE_DELIMITER) + 1));
        this.entity = entity;
        this.setLocalizationKey(entity.getLocalizationKey());
        this.queryGenerator = new QueryGenerator.Empty();
    }

    public View(Entity entity, String id) {
        super(entity.getId().substring(entity.getId().indexOf(TYPE_DELIMITER) + 1) + SUFFIX_DELIMITER + id);
        this.entity = entity;
        this.setLocalizationKey(entity.getLocalizationKey() + "." + id);
        this.queryGenerator = new QueryGenerator.Empty();
    }

    public View(View masterView, String id) {
        super(masterView.getId().substring(masterView.getId().indexOf(TYPE_DELIMITER) + 1)+ SUFFIX_DELIMITER + id);
        this.entity = masterView.entity;
        this.setLocalizationKey(masterView.getLocalizationKey()+"."+id);
        this.queryGenerator = masterView.queryGenerator;
        this.trigger=masterView.trigger;
        this.properties=masterView.properties;
        this.sortProperty=masterView.sortProperty;
        this.form=masterView.form;
        this.pageSize=masterView.pageSize;
    }

    public List<Property<? extends Serializable>> getProperties() {
        return properties;
    }

    public View addProperty(Property<? extends Serializable> property) {
        Preconditions.checkArgument(property!=null, "Attempted to add null property to view: "+this.entity);
        properties.add(property);
        return this;
    }

    public Entity getEntity() {
        return entity;
    }

    public int getPageSize() {
        return pageSize;
    }

    public View setPageSize(int pageSize) {
        this.pageSize = pageSize;
        return this;
    }

    public ViewDTO getViewDTO(Context ctx) {
        ViewDTO viewDTO = new ViewDTO(this.getId(), this.getLocalizedName(ctx), this.getPageSize());
        EntityDTO ent = new EntityDTO(entity.getId(), entity.getLocalizedName(ctx));
        viewDTO.setEntity(ent);
        for (Property<? extends Serializable> p : this.getProperties()) {
            viewDTO.addProperty(p.clientClone(ctx));
        }
        if (sortProperty != null) {
            viewDTO.setSortProperty(sortProperty.clientClone(ctx));
        }
        viewDTO.setQueryParameters(this.queryGenerator.getQueryParameters(ctx));
        viewDTO.setFormDescriptor(createFormDescriptor(ctx));
        return viewDTO;
    }

    private FormDTO createFormDescriptor(Context ctx) {
        Form f = getForm(ctx);
        FormDTO retval = new FormDTO(f.getId(), f.getLocalizedName(ctx));
        retval.setLayout(f.getLayout().getWidgetDescriptor(ctx));
        return retval;
    }

    public Property<? extends Serializable> getSortProperty() {
        return sortProperty;
    }

    public View setSortProperty(Property<? extends Serializable> sortProperty) {
        this.sortProperty = sortProperty;
        return this;
    }

    public PersisterTriggers getPersisterTriggers(Context ctx) {

        // TODO use context to select trigger?
        return this.trigger;
    }

    public View setPersistersTriggers(PersisterTriggers triggers) {
        this.trigger = triggers;
        return this;
    }

    public QueryGenerator getQueryGenerator() {
        return queryGenerator;
    }

    public View setQueryGenerator(QueryGenerator queryGenerator) {
        this.queryGenerator = queryGenerator;
        return this;
    }

    public Form getForm(Context context) {
        return form;
    }

    public View setForm(Form form) {
        this.form = form;
        return this;
    }

    public View form(Widget layout) {
        return setForm(Form.form(layout));
    }
}
